#include "../bulk_storage/bulk_storage.h"
#include "aa_neighborhood.h"
#include "../m_tree/mTree.h"
#include "../m_tree/mTreeNode.h"
#include "../query_handler/query_handler.h"
#include <stdlib.h>

#include <sys/timeb.h>


void aa_neighborhood_print_hit(struct aa_neighborhood * n, void * state) {
  //  aa_neighborhood_print(n);
}

int main (int argc, char * argv[]) {
  struct store * db, * q;
  struct mTree * db_mTree;
  struct aa_neighborhood * n;
  struct mTreeNode * tmpNode;
  unsigned short start, stop;
  struct timeb ts;
  off_t i = 0;
  off_t node_store_size;
  int last;
  if(argc != 8) {
    printf("This program expects exactly seven arguments; a query radius, the database neighbor store, its fat, the datbase index, its fat, the query neighbor store, and its fat\n");
    return 1;
  }

  db = store_open_cached(argv[2],argv[3],sizeof(struct aa_neighborhood), 100, 10000000);
  db_mTree = mTree_open_cached(db, argv[4], argv[5], 3500000, (double(*)(const void*,const void*))&aa_neigh_dist);
  q  = store_open_cached(argv[6],argv[7],sizeof(struct aa_neighborhood), 100, 1000);

  tmpNode = store_read(db_mTree->nStore, 0);
  i = 0;

  ftime(&ts);
  start = ts.time;

  printf("Pre-reading tree nodes..\n");
  last = 100;
  //  while(tmpNode->children[0] != 0) {
  while(last) {
    i++;
    tmpNode = store_read(db_mTree->nStore, i);
    last --;
    if(tmpNode->children[0] != 0) {
      last = 100;
    }
  }

  ftime(&ts);
  stop = ts.time;

  printf("..Done reading tree nodes.  # = %ld Time = %d\n", (long int)i, stop - start);

  node_store_size = i;

  ftime(&ts);
  start = ts.time;

  printf("Pre-reading objects..\n");
  i =0;
  n = store_read(db, i);
  last = 100;
  while(last && i < 10000000) {

    if(n->pdb_name[0] == 0) {
      last--;
    } else {
      last = 100;
    }

    store_release(db, i);
    i++;
    n = store_read(db, i);
  }
  store_release(db, i);

  ftime(&ts);
  stop = ts.time;

  printf("..Done reading objects.  # = %ld (of size = %ld) time = %d\n", (long int)i, (long int)sizeof(struct aa_neighborhood), stop-start);
  i = 0;
  n = store_read(q, i);



  while(n->pdb_name[0] && i >= 0) {
    off_t hits = 0;
    ftime(&ts);
    start = ts.time;
    
    printf("Running query: \n");
    //    aa_neighborhood_print(n);

    //    mTree_rangeQuery(db_mTree, n, atoi(argv[1]), (void(*)(void*,void*))&aa_neighborhood_print_hit, 0);
    mTree_rangeQuery(db_mTree, n, atoi(argv[1]), (void(*)(void*,void*))&count_hits, &hits);
    store_release(q, i);
    ftime(&ts);
    stop = ts.time;
    
    printf("Query completed.  Time = %d #hits = %ld\n", stop-start, (long)hits);

    //i = -1;
    i++;
    n = store_read(q,i);
  }
  
  store_release(q,i);

  cs_print(db->store_p);
  cs_print(db_mTree->nStore->store_p);

  for(i = 0; i <= node_store_size; i++) {
    store_release(db_mTree->nStore, i);
  }

  store_close(q);
  mTree_close(db_mTree);
  store_close(db);
  
  return 0;

}
